package com.github.hgbit.utils;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
import com.github.hgbit.JsonUtil;
import com.github.hgbit.filter.RepeatReadRequestWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.Charsets;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.util.WebUtils;

import java.io.IOException;
import java.util.Arrays;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

/**
 * RequestContentUtil.
 *
 * @author huangguan
 * @since 2019-03-13
 */
@Slf4j
public class RequestContentUtil {

    private static ObjectMapper mapper = new ObjectMapper();

    static {
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL)
            .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
            .registerModule(new ParameterNamesModule())
            .registerModule(new Jdk8Module())
            .registerModule(new JavaTimeModule());
    }

    /**
     * 获取RequestBody.
     *
     * @param request request
     * @param type    转换后的java类型
     * @param <T>     转换后的java类型
     * @return target class of type
     */
    public static <T> T getRequestBody(HttpServletRequest request, Class<T> type) {
        String content = convertRequestBody2JsonStr(request);
        return StringUtils.isBlank(content) ? null : JsonUtil.fromJson(content, type);
    }

    /**
     * 获取RequestBody.
     *
     * @param request request
     * @param type    转换后的java类型
     * @param <T>     转换后的java类型
     * @return target class of type
     */
    public static <T> T getRequestBody(HttpServletRequest request, TypeReference type) {
        return JsonUtil.fromJson(convertRequestBody2JsonStr(request), type);
    }

    /**
     * request转JsonString.
     *
     * @param request request
     * @return String
     */
    private static String convertRequestBody2JsonStr(HttpServletRequest request) {
        try {
            if (request.getContentLength() > 0) {
                RepeatReadRequestWrapper requestWrapper =
                    WebUtils.getNativeRequest(request, RepeatReadRequestWrapper.class);
                byte[] array = IOUtils.toByteArray(requestWrapper.getInputStream());
                return new String(array, Charsets.UTF_8);
            }
        } catch (IOException e) {
            log.error("request转JsonString失败！", e);
        }
        return StringUtils.EMPTY;
    }

    /**
     * 读取RequestParam值.
     *
     * @param request   request
     * @param paramName 参数名
     * @return String
     */
    public static String findParamValue(HttpServletRequest request, String paramName) {
        String parameter = request.getParameter(paramName);
        if (StringUtils.isBlank(parameter)) {
            parameter = request.getHeader(paramName);

            if (StringUtils.isBlank(parameter)) {
                if (request.getCookies() == null || request.getCookies().length == 0) {
                    return null;
                }
                parameter = Arrays.stream(request.getCookies())
                    .filter(cookie -> StringUtils.equalsIgnoreCase(cookie.getName(), paramName)
                    ).findFirst().orElse(new Cookie(paramName, "")).getValue();
            }
        }
        return parameter;
    }
}
